package com.example.user1.config;

import com.example.user1.util.JwtTokenGenerate;
import com.example.user1.util.TokenGenerateUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBucket;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.redisson.codec.JacksonCodec;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.codec.SerializationCodec;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.*;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

@Configuration
@Component
@Slf4j
public class AutoConfig {
    public final static String PUBLIC_KEY = "public_key";
    public final static String PRIVATE_KEY = "private_key";
    public final static String RSA = "RSA";

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public RSAPrivateKey rsaPrivateKey(RedissonClient redissonClient) throws NoSuchAlgorithmException {
        RMap<String, Object> map = redissonClient.getMap(RSA, new SerializationCodec());
        if (map.containsKey(PUBLIC_KEY) && map.containsKey(PRIVATE_KEY)) {
            RSAPrivateKey privateKey = (RSAPrivateKey) map.get(PRIVATE_KEY);
            log.info("RSAPrivateKey: {}", privateKey.toString());
            return privateKey;
        }
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        map.put(PUBLIC_KEY, publicKey);
        map.put(PRIVATE_KEY, privateKey);
        log.info("RSAPrivateKey: {}", privateKey.toString());
        return privateKey;
    }

    @Bean
    @ConditionalOnBean(RSAPrivateKey.class)
    public TokenGenerateUtil tokenGenerateUtil(RSAPrivateKey rsaPrivateKey) {
        return new JwtTokenGenerate(rsaPrivateKey);
    }
}
